        TITL DAI FIRMWARE CA01-CBBE  V1.0  Rev.1
        ORG   :CA01
*
*
*
*****************************
* MEMORY MANAGEMENT ROUTINE *
*****************************
*
* This routine is used to obtain and release
* memory for its display, as the mode changes.
*
* Entry: HL: Lowest screen RAM byte required.
*        CY=1: Space to this point at least is
*              now required. Additional space
*              may not be released.
*        CY=0: Space is held to or below this
*              point. Any space held below this
*              point is no longer required.
* Exit:  CY=1: O.K.
*        CY=0: No space available.
*        AFBCDE preserved.
*
*ASKRM
SMKRM   NOP
        PUSH  PSW
        PUSH  D
        JNC   :CA1B     If space not reqd anymore
        XCHG            Lowest byte in DE
        LHLD  :02A5     Get bottom screen RAM
        CALL  :DE14     Check for overflow
        JC    :CA1E     If OK
        LHLD  :02A3     Get begin free RAM
        XCHG            and store it in DE
        CALL  :DE14     Still free RAM available?
        JC    :CA21     If not
ASR10   SHLD  :02A5     Update bottom screen RAM
ASR20   JMP   :CEAD     Return, set CY=1
 REM
* If no RAM space available:
 REM
ASR30   POP   D
        JMP   :CEB1     Return, set CY=0
*
*******************************************
* EMERGENCY STOP ROUTINE (Graphics modes) *
*******************************************
*
* This routine is used if no sufficient space for
* a A-mode is available.
*
EMSTP   CALL  :CEC6     Set up HEAPsize + buffers
 REM to default values
        MVI   A,:FF
        RST   5         Change to mode 0
        DATA  :18
        CALL  :CEE4     Select ROM-bank 0; Run error
        DBL   :DB89     'OUT OF SPACE FOR MODE'
        JMP   :C818     Return to BASIC monitor
*
******************************************
* FIND STRING BASIC INSTRUCTION IN TABLE *
******************************************
*
* Looks for table entry whose name is the initial
* string of input, beginning at C'th position.
* REMARK: Variables, beginning with a reserved
*         string are not allowed.
*
* Entry: HL: Startaddress table.
*        C : Position char on current line.
*        E : Number of info bytes -1.
* Exit:  If found: CY=1:
*            HL: Address in table where string
*                can be found.
*            C : Position on current line after
*                last char.
*            A : Last byte of string typed in.
*            BE preserved, D=0.
*        If not found: CY=0:
*            C : Points to next char.
*            HL: Points after end of table.
*            BE preserved. A,D=0.
*
LOOKC   CALL  :DDD2     Get char from line,
 REM neglect TAB and space
LKC10   MOV   D,M       Get length byte of string
        INX   H         Points to 1st stringchar.
        MOV   A,D
        ORA   A         Is length zero?
        RZ              Then abort
        PUSH  B         Save position of 1st char
LKC20   CALL  :DDE0     Get char from line
        INR   C         Points to next char on line
        CMP   M         Is it identical to the
 REM one in table?
        INX   H         Points to next char in table
        JNZ   :CA4E     If not identical
        DCR   D         Else: decr string length
        JNZ   :CA3D     Get evt. next byte to check
        XTHL            cancell PUSH B
        POP   H
        STC             CY=1
        RET
 REM
* If strings not identical:
 REM
LKC30   MOV   A,D       Get string length
        ADD   E         Add 2
        CALL  :DE30     Add A to HL; HL points now
 REM to next string in table.
        POP   B         Restore C=1
        JMP   :CA37     Start check on next string
*
*****************
* TABLE LOOK UP *
*****************
*
* Finds an entry in a look-up table.
* LOOK used for symboltable, LOOKX for table of
* Basic functions (CFE6).
*
* Table format:
* [type/length][name][type/length][info]
*
* Entry: B:  Points to start name in input.
*        D:  Type/length of name in input
*            high nibble: type; low nibble: length.
*        HL: Startaddress look-up table.
* Exit:  If not found: CY=0:
*            HL points to 0 byte at table end.
*            ABCD preserved, E corrupted.
*        If found: CY=1:
*            HL points to T/L of entry found.
*            E indicates how manyth entry.
*            ABC preserved.
*
LOOK    LHLD  :02A1     Get startaddr symtab
*
LOOKX   STC             CY=1
        PUSH  PSW
        PUSH  B
        MVI   E,:FF
LK10    INR   E         Entry count
        MOV   A,M       Get T/L name in table
        ORA   A
        JZ    :CA8B     Abort if end table reached
        CMP   D         Compare with wanted T/L
        JZ    :CA6F     Jump if found
LK15    CALL  :CAAE     Calc addr next entry
        JMP   :CA5F     Check next entry
 REM
* If T/L of name O.K.:
 REM
LK20    POP   B
        PUSH  B
        MOV   C,B
        PUSH  D
        MOV   A,D       Get wanted T/L of name
        ANI   :0F       Length name only
        MOV   D,A       in D
        PUSH  H         Save begin table entry
LK30    INX   H
        CALL  :DDE0     Get char from line
        CMP   M         Compare char of name
        JNZ   :CA8F     If not correct name
 REM
* If char. identical:
 REM
        INR   C         Points to next char
        DCR   D         Decr length
        JNZ   :CA78     Check next char if not
 REM ready
        INX   H         Points after name in table
        POP   D
        POP   D
        POP   B
        POP   PSW       CY=1: Entry found
        RET
 REM
* If end of look-up table reached:
 REM
LK40    POP   B
        POP   PSW
        CMC             CY=0: No entry found
        RET
 REM
* If characters not identical:
 REM
LK50    POP   H
        POP   D
        MOV   A,D       Length in A
        JMP   :CA69     Look further
*
**************************************
* FIND A VARIABLE IN THE SYMBOLTABLE *
**************************************
*
* Routine skips through successive symtab entries
* from beginning till past the place pointed by HL.
*
* Entry: HL points to 1st byte required variable.
* Exit:  HL points to (if found) or past (if not
*        found) address required in symbol table.
*        AFBCDE preserved.
*
FNAME   PUSH  PSW
        PUSH  D
        XCHG            Reqd addr in DE
        LHLD  :02A1     Get startaddr symtab
FNM10   PUSH  H
        CALL  :CAAE     Calc addr next variable
        CALL  :DE14     Reqd variable reached ?
        JNC   :CAAA     Quit if true
        INX   SP        ) Cancel Push H
        INX   SP        )
        JMP   :CA9B     Skip next variable
FNM20   POP   H
        POP   D
        POP   PSW
        RET
*
**************************************************
* CALCULATE ADDRESS NEXT VARIABLE IN SYMBOLTABLE *
**************************************************
*
* Adds length of name of variable + length of value
* of variable to beginaddress.
*
* DADD: variable = length/name/length/value.
* DADR: variable = length/name.
*
* Entry: HL points to 1st byte of current variable.
* Exit:  HL points to next variable in symtab.
*
DADD    CALL  :CAB1     Add length name to HL
DADR    MOV   A,M       Get info T/L byte
        INX   H         Add 1
        ANI   :0F       Length only
        JMP   :DE30     Add length info to HL
*
**********************************************
* INSERT A VARIABLE NAME IN THE SYMBOL TABLE *
**********************************************
*
* Entry: HL points to end symtab.
*        B  points to start of name in input.
*        E  number of bytes of info to reserve.
*        D  T/L byte of name.
* Exit:  HL points to info T/L byte.
*        AFBCDE preserved.
*
LOOKI   PUSH  PSW
        PUSH  B
        MOV   C,B       Input pos. in C
        PUSH  D
        PUSH  D
        PUSH  H
        MOV   A,D       T/L name in A
        ANI   :0F       Name length only
        ADD   E         Add length info
        INR   A
        INR   A         +2 (length new entry)
        CALL  :DE30     Calc new end symtab -1
        XCHG
        LHLD  :02A5     Get bottom screen RAM
        XCHG
        CALL  :DE14     Compare DE-HL
        MVI   A,:1B
        JNC   :D9F5     Run 'OUT OF MEMORY' if
 REM not sufficient free RAM
        MVI   M,:00     New 'end table' flag
        INX   H         HL is new end symtab
        SHLD  :02A3     Store end symtab
        POP   H         Get old end symtab
        POP   D         Get T/L info
        MOV   M,D       Into symtab
        INX   H
        MOV   A,D
        ANI   :70       Get type only
        ORA   E         Set low nibble for length
        MOV   E,A
        MOV   A,D       Get length name
        ANI   :0F       Max. 15 bytes
        MOV   D,A       Length in D for count
LKI10   CALL  :DDE0     Get char from line
        MOV   M,A       Char into symtab
        INR   C         Pnts to next char on line
        INX   H         Next pos in symtab
        DCR   D         Decr length name
        JNZ   :CAE7     Next char if not ready
        MOV   M,E       Info T/L into symtab
        POP   D
        POP   B
        POP   PSW
        RET
*
*********************************
* FIND LINENUMBER IN TEXTBUFFER *
*********************************
*
* Entry: HL: requested linenumber.
* Exit:  ABCDE preserved. F corrupted.
*        CY=1: Linenr found:
*              HL points to address textline.
*        CY=0: Not found:
*              Z=0: HL points to address textline
*                   with next higher linenumber.
*              Z=1: End of textbuffer reached.
*
FINDL   PUSH  B
        PUSH  PSW
        PUSH  D
        MVI   B,:00
        XCHG            Req. linenr in DE
        LHLD  :029F     Get startaddr textbuf
FDL05   MOV   C,B       Length prev. instr in C
        MVI   B,:00
        DAD   B         Add this length to beginaddr
FDL10   MOV   B,M       Get length current instr
        MOV   A,B       in A
        ORA   A
        INX   H         Pnts to hibyte linenr
        JZ    :CB1D     Abort if at end textbuf
        MOV   A,D       Get hibyte reqd linenr.
        CMP   M         Test high order bits
        JC    :CB1C     Abort if reqd nr lower than
 REM current one (nr > reqd)
        JNZ   :CAFF     Next textline (nr < reqd)
        INX   H         Pnts to lobyte linenr
        MOV   A,E       Get lobyte reqd linenr
        CMP   M
        DCX   H
        JC    :CB1C     Abort if reqd nr lower than
 REM current one (nr > reqd)
        JNZ   :CAFF     Next textline if not found
 REM (nr < reqd)
FDL20   CMC             Line found: CY=1
FDL30   DCX   H
        POP   D
        POP   B
        MOV   A,B
        POP   B
        RET
*
******************************
* EMPTY SYMBOLTABLE AND HEAP *
******************************
*
* Zeroes all variables, all pointers in the symtab,
* kill all arrays, strings or stringarrays (zero the
* pointers) referenced by the symtab by setting the
* msb of the sizebit =1. Basic program is moved to a
* location corresponding to the Heapsize.
*
* Exit: All registers preserved.
*
SCRATC  PUSH  PSW
        PUSH  B
        PUSH  D
        PUSH  H
        LHLD  :02A1     Get startaddr symtab
SCT10   MOV   A,M       ) get name length
        ANI   :0F       )
        JZ    :CB53     Abort if at end symtab
        CALL  :CAB1     HL pnts to info length byte
        MOV   A,M       ) Get type
        ANI   :F0       )
        CPI   :40
        JNC   :CB4D     If array
        INX   H
        CPI   :20
        JZ    :CB47     If string
 REM
* If numeric variable:
 REM
        CALL  :CB9E     Set value is 0 (4 bytes)
        JMP   :CB2A     Next entry
 REM
* If string variable:
 REM
SCT30   CALL  :CBA8     Erase string reference in
 REM symbtab and Heap
        JMP   :CB2A     Next entry
 REM
* If array:
 REM
SCT40   CALL  :CB5B     Erase array
        JMP   :CB2A     Next entry
 REM
* If ready:
 REM
SCT90   CALL  :DECA     Organise HEAP + buffers
LC188   POP   H
        POP   D
        POP   B
        POP   PSW
        RET
*
***************
* ERASE ARRAY *
***************
*
* The pointer is zeroed, the array size is erased
* (msb=1). For stringarrays: zeroes all pointers
* in the array and erase the string in the Heap.
*
* Entry: HL points to T/L byte of info after a
*           symtab name of an array.
* Exit:  HL points to next symtab entry.
*        AFBCDE preserved.
*
EARRAY  PUSH  D
        PUSH  B
        PUSH  PSW
        MOV   A,M       Get type info
        ANI   :30
        PUSH  PSW       Save type only
        CALL  :CE51     ) Get addr of array in
        INX   H         ) Heap in DE,
        MOV   D,M       ) Kill pointer in the
        MVI   M,:00     ) symboltable
        INX   H         Pnts after symtab entry
        MOV   A,D
        ORA   E
        JZ    :CB99     Abort if entry was already 0
        XCHG            Arrayaddr in HL
        DCX   H
        DCX   H         Pnts to 1st byte Heap entry
        MOV   B,M       Get 1st byte
        CALL  :D236     Clear heap entry by msb=1
        POP   PSW       Get type info
        PUSH  PSW
        CPI   :20       String ?
        PUSH  D         Save stringpointer
        JNZ   :CB98     Abort if not string
 REM
* If string array:
 REM
        INX   H
        MOV   C,M       Get length Heap entry
        INX   H
        MOV   E,M       Get dimension
        INR   E
        MOV   A,E
        CALL  :DE30     Calc beginaddr stringpntrs
        MOV   A,C
        SUB   E         Calc length pntr area
        MOV   C,A       in C
        JNC   :CB8E
        DCR   B
EAR10   CALL  :CBA8     Erase stringreference in
 REM symtab and Heap
        DCX   B
        DCX   B         Update length pntr area
        MOV   A,B
        ORA   C
        JNZ   :CB8E     Next string if not ready
 REM
* If ready:
 REM
EAR20   POP   H         Get symtab pntr
EAR30   POP   PSW
        POP   PSW
        POP   B
        POP   D
        RET
*
***********************************************
* CLEAR A NUMERIC VARIABLE IN THE SYMBOLTABLE *
***********************************************
*
* Loads '0' into 4 consecutive memory locations.
*
* Entry: Startaddress in HL.
* Exit:  A=0, HL points to next byte.
*        BCDEF preserved.
*
ZFPINT  XRA   A
        MOV   M,A
        INX   H
        MOV   M,A
        INX   H
        MOV   M,A
        INX   H
        MOV   M,A
        INX   H
        RET
*
********************************************
* ERASE STRINGREFERENCE IN HEAP AND SYMTAB *
********************************************
*
* The pointer in the symtab is set to '0', the
* msb of the sizebyte of the Heap entry is set
* to 1.
*
* Entry: HL points to stringpointer in symtab.
* Exit:  HL points after this pointer.
*        DE stringpointer.
*        BC preserved, AF corrupted
*
RSVHL   MOV   E,M       ) Stringpointer
        MVI   M,:00     ) in DE and then
        INX   H         ) erased.
        MOV   D,M       )
        MVI   M,:00     )
        INX   H
        PUSH  H
        LHLD  :029F     Get startaddr textbuf
        XCHG            in DE; stringpntr in HL
        MOV   A,H
        ORA   L         Stringpntr is already 0 ?
        CNZ   :DE14     If not: test if end of
 REM heap reached
        CC    :D187     If not: clear heap entry
        POP   H
        RET
*
*
*
        UNL
ASKRM   EQU SMKRM
        LST
        END
